//      graphscene.cpp
//      

#include "graphscene.h"
#include <QDebug>

GraphScene::GraphScene(QVector<quint16>* vertex_path, QObject* parent)
	: QGraphicsScene(parent), vertex_path(vertex_path)
{
	scale = 10;
	vertexDiam = 4 * scale;
	initializeVertexCoordinates();
	drawVertex();
	drawArrows();
	addTextLabels();
}

void GraphScene::addTextLabels() {
	const quint16 shiftX = 10;
	const quint16 shiftY = 7;
	QFont font("Arial", 14, QFont::Bold);
	QGraphicsItem* addedText = addText("0", font);
	addedText->setPos(vc[0].x() * scale + shiftX, vc[0].y() * scale + shiftY);
	addedText = addText("0", font);
	addedText->setPos(vc[1].x() * scale + shiftX, vc[1].y() * scale + shiftY);
	addedText = addText("1", font);
	addedText->setPos(vc[2].x() * scale + shiftX, vc[2].y() * scale + shiftY);
	addedText = addText("2", font);
	addedText->setPos(vc[3].x() * scale + shiftX, vc[3].y() * scale + shiftY);
	addedText = addText("0", font);
	addedText->setPos(vc[4].x() * scale + shiftX, vc[4].y() * scale + shiftY);
	addedText = addText("1", font);
	addedText->setPos(vc[5].x() * scale + shiftX, vc[5].y() * scale + shiftY);
	addedText = addText("2", font);
	addedText->setPos(vc[6].x() * scale + shiftX, vc[6].y() * scale + shiftY);
	addedText = addText("3", font);
	addedText->setPos(vc[7].x() * scale + shiftX, vc[7].y() * scale + shiftY);
	addedText = addText("1", font);
	addedText->setPos(vc[8].x() * scale + shiftX, vc[8].y() * scale + shiftY);
	
	QFont labelFont("Arial", 8, QFont::Normal);
	QGraphicsItem* labelText = addText("x1=3", labelFont);
	labelText->setPos(vc[0].x() * scale + 30, vc[0].y() * scale - 25);
	labelText = addText("x1=4", labelFont);
	labelText->setPos(vc[0].x() * scale + 50, vc[0].y() * scale);
	labelText = addText("x1=5", labelFont);
	labelText->setPos(vc[0].x() * scale + 30, vc[0].y() * scale + 35);
	
	labelText = addText("x2=4", labelFont);
	labelText->setPos(vc[1].x() * scale + 35, vc[1].y() * scale - 15);
	labelText = addText("x2=5", labelFont);
	labelText->setPos(vc[1].x() * scale + 50, vc[1].y() * scale + 8);
	
	labelText = addText("x2=3", labelFont);
	labelText->setPos(vc[2].x() * scale + 30, vc[2].y() * scale - 25);
	labelText = addText("x2=4", labelFont);
	labelText->setPos(vc[2].x() * scale + 50, vc[2].y() * scale - 9);
	labelText = addText("x2=5", labelFont);
	labelText->setPos(vc[2].x() * scale + 45, vc[2].y() * scale + 10);
	
	labelText = addText("x2=2", labelFont);
	labelText->setPos(vc[3].x() * scale + 30, vc[3].y() * scale - 25);
	labelText = addText("x2=3", labelFont);
	labelText->setPos(vc[3].x() * scale + 50, vc[3].y() * scale - 12);
	labelText = addText("x2=4", labelFont);
	labelText->setPos(vc[3].x() * scale + 45, vc[3].y() * scale + 8);
	labelText = addText("x2=5", labelFont);
	labelText->setPos(vc[3].x() * scale + 40, vc[3].y() * scale + 30);
	
	labelText = addText("x3=3", labelFont);
	labelText->setPos(vc[4].x() * scale + 40, vc[4].y() * scale + 20);
	
	labelText = addText("x3=2", labelFont);
	labelText->setPos(vc[5].x() * scale + 40, vc[5].y() * scale + 10);
	
	labelText = addText("x3=1", labelFont);
	labelText->setPos(vc[6].x() * scale + 40, vc[6].y() * scale - 15);
	
	labelText = addText("x3=0", labelFont);
	labelText->setPos(vc[7].x() * scale + 40, vc[7].y() * scale - 35);
	
}

void GraphScene::drawVertex()
{
	addEllipse(vc[0].x() * scale, vc[0].y() * scale, vertexDiam, vertexDiam); // 0 vertex
	addEllipse(vc[1].x() * scale, vc[1].y() * scale, vertexDiam, vertexDiam); // 1 vertex
	addEllipse(vc[2].x() * scale, vc[2].y() * scale, vertexDiam, vertexDiam); // 2 vertex
	addEllipse(vc[3].x() * scale, vc[3].y() * scale, vertexDiam, vertexDiam); // 3 vertex
	addEllipse(vc[4].x() * scale, vc[4].y() * scale, vertexDiam, vertexDiam); // 4 vertex
	addEllipse(vc[5].x() * scale, vc[5].y() * scale, vertexDiam, vertexDiam); // 5 vertex
	addEllipse(vc[6].x() * scale, vc[6].y() * scale, vertexDiam, vertexDiam); // 6 vertex
	addEllipse(vc[7].x() * scale, vc[7].y() * scale, vertexDiam, vertexDiam); // 7 vertex
	addEllipse(vc[8].x() * scale, vc[8].y() * scale, vertexDiam, vertexDiam); // 8 vertex
}

void GraphScene::initializeVertexCoordinates() {
	vc[0] = QPoint(0, 15);
	vc[1] = QPoint(20, 5);
	vc[2] = QPoint(20, 15);
	vc[3] = QPoint(20, 25);
	vc[4] = QPoint(40, 0);
	vc[5] = QPoint(40, 10);
	vc[6] = QPoint(40, 20);
	vc[7] = QPoint(40, 30);
	vc[8] = QPoint(60, 15);
}

void GraphScene::drawArrows() {
	drawArrowByVertex(0, 1);
	drawArrowByVertex(0, 2);
	drawArrowByVertex(0, 3);
	drawArrowByVertex(1, 4);
	drawArrowByVertex(1, 5);
	drawArrowByVertex(2, 4);
	drawArrowByVertex(2, 5);
	drawArrowByVertex(2, 6);
	drawArrowByVertex(3, 4);
	drawArrowByVertex(3, 5);
	drawArrowByVertex(3, 6);
	drawArrowByVertex(3, 7);
	drawArrowByVertex(4, 8);
	drawArrowByVertex(5, 8);
	drawArrowByVertex(6, 8);
	drawArrowByVertex(7, 8);
}

void GraphScene::drawArrow(qreal x1, qreal y1, qreal x2, qreal y2, bool fat)
{
	quint16 h = 10;
	quint16 w = 3;
	QPen pen;
	if (fat) {
		pen.setWidth(3);
	}
	addLine(x1, y1, x2, y2, pen);
	qint16 a = x2 - x1;
	qint16 b = y2 - y1;
	qreal c = sqrt(a * a + b * b);
	qreal ex = a / c;
	qreal ey = b / c;
	qreal x3 = x2 - h * ex;
	qreal y3 = y2 - h * ey;
	qreal ny = -ex;
	qreal nx = ey;
	qreal x4 = x3 + (nx * w);
	qreal y4 = y3 + (ny * w);
	qreal x5 = x3 - (nx * w);
	qreal y5 = y3 - (ny * w);
	QPolygonF arrow;
	arrow << QPointF(x2, y2) << QPointF(x4, y4) << QPointF(x3 + (3 * ex), y3 + (3 * ey))
			<< QPointF(x5, y5);
	addPolygon(arrow, pen, QBrush(Qt::black));
}

void GraphScene::drawArrowByVertex(quint16 v1, quint16 v2)
{
	/******************************************************************
	* TO-DO: Избавиться от переменной dir
	**/
	qreal r = vertexDiam / (2 * scale);
	QPoint p1 = QPoint(vc[v1].x() + r, vc[v1].y() + r);
	QPoint p2 = QPoint(vc[v2].x() + r, vc[v2].y() + r);
	qint16 a = (p2.x() - p1.x()) * scale;
	qint16 b = (p1.y() - p2.y()) * scale;
	qint16 dir = 0;
	if (b > 0) {
		dir = -1;
	} else if (b < 0) {
		dir = 1;
	}
	qreal k = (r * scale) / (sqrt(a * a + b * b));
	qreal dx = k * a;
	qreal dy = k * abs(b);
	bool make_fat = false;
	if (vertex_path) {
		if (vertex_path->contains(v1) && vertex_path->contains(v2)) {
			make_fat = true;
		}
	}
	drawArrow(p1.x() * scale + dx, (p1.y() * scale) + dy * dir,
			p2.x() * scale - dx, (p2.y() * scale) - dy * dir, make_fat);
}




